{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "af3f88dd-0f5e-427e-84ee-8934982300d1",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Bedrock with LangChain - Explain/Interpret a code snippet or program \n",
    "> *This notebook should work well with the **`Data Science 3.0`** kernel in SageMaker Studio*"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59f874c8b3d23145",
   "metadata": {},
   "source": [
    "## Introduction\n",
    "\n",
    "In this notebook we show you how to explain or interpret a given code snippet or program.\n",
    "\n",
    "[LangChain](https://python.langchain.com/docs/get_started/introduction.html) is a framework for developing applications powered by language models. The key aspects of this framework allow us to augment the Large Language Models by chaining together various components to create advanced use cases.\n",
    "\n",
    "In this notebook we will use the Bedrock API provided by LangChain. The prompt used in this example creates a custom LangChain prompt template for adding context to the code explain request. \n",
    "\n",
    "**Note:** *This notebook can be run within or outside of AWS environment.*\n",
    "\n",
    "#### Context\n",
    "In this notebook we will leverage the LangChain framework and explore Bedrock API with the help of `PromptTemplates`. `PrompTemplates` allow you to create generic shells which can be populated with information later and get model outputs based on different scenarios.\n",
    "\n",
    "As part of this notebook we will explore the use of Amazon Bedrock integration within LangChain framework and how it could be used to generate or explain code with the help of `PromptTemplate`.\n",
    "\n",
    "#### Pattern\n",
    "We will simply provide the LangChain implementation of Amazon Bedrock API with an input consisting of a task, an instruction and an input for the model under the hood to generate an output without providing any additional example. The purpose here is to demonstrate how the powerful LLMs easily understand the task at hand and generate compelling outputs.\n",
    "\n",
    "![](./images/code-interpret-langchain.png)\n",
    "\n",
    "#### Use case\n",
    "To demonstrate the code generation capability of models in Amazon Bedrock, let's take the use case of code explain.\n",
    "\n",
    "#### Persona\n",
    "You are Joe, a Java software developer, has been tasked to support a legacy C++ application for Vehicle Fleet Management. You need help to explain or interpret certain complex C++ code snippets as you are performing analyis to identify the business logic and potential problems with the code.\n",
    "\n",
    "#### Implementation\n",
    "To fulfill this use case, we will show you how you can Amazon Bedrock API with LangChain to explain C++ code snippets.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "66453a5c93c11f97",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T19:31:59.588187Z",
     "start_time": "2025-02-13T19:31:59.583048Z"
    }
   },
   "outputs": [],
   "source": [
    "from IPython.core.display import HTML\n",
    "from IPython.display import display_markdown, Markdown\n",
    "import boto3\n",
    "\n",
    "HTML(\"<script>Jupyter.notebook.kernel.restart()</script>\")\n",
    "boto3_bedrock = boto3.client('bedrock-runtime')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7daa1a8-d21a-410c-adbf-b253c2dabf80",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Invoke the Bedrock LLM Model\n",
    "\n",
    "We'll begin with creating an instance of Bedrock class from llms. This expects a `model_id` which is the ARN of the model available in Amazon Bedrock. \n",
    "\n",
    "Optionally you can pass on a previously created boto3 client as well as some `model_kwargs` which can hold parameters such as `temperature`, `topP`, `maxTokenCount` or `stopSequences` (more on parameters can be explored in Amazon Bedrock console).\n",
    "\n",
    "Check [documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids-arns.html) for Available text generation model Ids under Amazon Bedrock.\n",
    "\n",
    "Note that different models support different `model_kwargs`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "8ffa1250-56cd-4b6d-b3d8-c62baac143ce",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T19:32:04.889693Z",
     "start_time": "2025-02-13T19:32:04.419706Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from langchain_aws import ChatBedrockConverse\n",
    "\n",
    "\n",
    "textgen_llm = ChatBedrockConverse(\n",
    "    model_id=\"us.amazon.nova-lite-v1:0\",\n",
    "    client=boto3_bedrock,\n",
    "    max_tokens=None,\n",
    "    temperature=0.5\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de2678ed-f0d6-444f-9a57-5170dd1952f7",
   "metadata": {},
   "source": [
    "## Create a LangChain custom prompt template\n",
    "\n",
    "By creating a template for the prompt we can pass it different input variables to it on every run. This is useful when you have to generate content with different input variables that you may be fetching from a database."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "884728e6fbd57043",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T19:32:09.022766Z",
     "start_time": "2025-02-13T19:32:09.014511Z"
    }
   },
   "outputs": [],
   "source": [
    "# Vehicle Fleet Management Code written in C++\n",
    "sample_code = \"\"\"\n",
    "#include <iostream>\n",
    "#include <string>\n",
    "#include <vector>\n",
    "\n",
    "class Vehicle {\n",
    "protected:\n",
    "    std::string registrationNumber;\n",
    "    int milesTraveled;\n",
    "    int lastMaintenanceMile;\n",
    "\n",
    "public:\n",
    "    Vehicle(std::string regNum) : registrationNumber(regNum), milesTraveled(0), lastMaintenanceMile(0) {}\n",
    "\n",
    "    virtual void addMiles(int miles) {\n",
    "        milesTraveled += miles;\n",
    "    }\n",
    "\n",
    "    virtual void performMaintenance() {\n",
    "        lastMaintenanceMile = milesTraveled;\n",
    "        std::cout << \"Maintenance performed for vehicle: \" << registrationNumber << std::endl;\n",
    "    }\n",
    "\n",
    "    virtual void checkMaintenanceDue() {\n",
    "        if ((milesTraveled - lastMaintenanceMile) > 10000) {\n",
    "            std::cout << \"Vehicle: \" << registrationNumber << \" needs maintenance!\" << std::endl;\n",
    "        } else {\n",
    "            std::cout << \"No maintenance required for vehicle: \" << registrationNumber << std::endl;\n",
    "        }\n",
    "    }\n",
    "\n",
    "    virtual void displayDetails() = 0;\n",
    "\n",
    "    ~Vehicle() {\n",
    "        std::cout << \"Destructor for Vehicle\" << std::endl;\n",
    "    }\n",
    "};\n",
    "\n",
    "class Truck : public Vehicle {\n",
    "    int capacityInTons;\n",
    "\n",
    "public:\n",
    "    Truck(std::string regNum, int capacity) : Vehicle(regNum), capacityInTons(capacity) {}\n",
    "\n",
    "    void displayDetails() override {\n",
    "        std::cout << \"Truck with Registration Number: \" << registrationNumber << \", Capacity: \" << capacityInTons << \" tons.\" << std::endl;\n",
    "    }\n",
    "};\n",
    "\n",
    "class Car : public Vehicle {\n",
    "    std::string model;\n",
    "\n",
    "public:\n",
    "    Car(std::string regNum, std::string carModel) : Vehicle(regNum), model(carModel) {}\n",
    "\n",
    "    void displayDetails() override {\n",
    "        std::cout << \"Car with Registration Number: \" << registrationNumber << \", Model: \" << model << \".\" << std::endl;\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    std::vector<Vehicle*> fleet;\n",
    "\n",
    "    fleet.push_back(new Truck(\"XYZ1234\", 20));\n",
    "    fleet.push_back(new Car(\"ABC9876\", \"Sedan\"));\n",
    "\n",
    "    for (auto vehicle : fleet) {\n",
    "        vehicle->displayDetails();\n",
    "        vehicle->addMiles(10500);\n",
    "        vehicle->checkMaintenanceDue();\n",
    "        vehicle->performMaintenance();\n",
    "        vehicle->checkMaintenanceDue();\n",
    "    }\n",
    "\n",
    "    for (auto vehicle : fleet) {\n",
    "        delete vehicle; \n",
    "    }\n",
    "\n",
    "    return 0;\n",
    "}\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "89d3bb62e5434e55",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T19:32:10.248926Z",
     "start_time": "2025-02-13T19:32:10.240908Z"
    }
   },
   "outputs": [],
   "source": [
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "# Create a prompt template that has multiple input variables\n",
    "multi_var_prompt = PromptTemplate(\n",
    "    input_variables=[\"code\", \"programmingLanguage\"], \n",
    "    template=\"\"\"\n",
    "\n",
    "Human: You will be acting as an expert software developer in {programmingLanguage}. \n",
    "You will explain the below code and highlight if there are any red flags or where best practices are not being followed.\n",
    "<code>\n",
    "{code}\n",
    "</code>\n",
    "\n",
    "Assistant:\"\"\"\n",
    ")\n",
    "\n",
    "# Pass in values to the input variables\n",
    "prompt = multi_var_prompt.format(code=sample_code, programmingLanguage=\"C++\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5b76387",
   "metadata": {},
   "source": [
    "### Explain C++ Code for Vehicle Fleet management using Amazon Bedrock and LangChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c1064c57-27a4-48c5-911b-e4f1dfeff122",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T19:32:25.874842Z",
     "start_time": "2025-02-13T19:32:12.402866Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "Certainly! Let's go through the code step by step and highlight any potential issues or areas where best practices could be improved.\n",
       "\n",
       "### Code Overview\n",
       "\n",
       "The code defines a hierarchy of classes for different types of vehicles. It includes a base class `Vehicle` and derived classes `Truck` and `Car`. Each class has methods to add miles, check for maintenance, perform maintenance, and display details.\n",
       "\n",
       "### Detailed Explanation\n",
       "\n",
       "#### Vehicle Class\n",
       "\n",
       "- **Protected Members**: \n",
       "  - `registrationNumber`: Stores the vehicle's registration number.\n",
       "  - `milesTraveled`: Tracks the total miles the vehicle has traveled.\n",
       "  - `lastMaintenanceMile`: Tracks the miles at the last maintenance.\n",
       "\n",
       "- **Constructor**: Initializes the registration number, sets miles traveled and last maintenance mile to 0.\n",
       "\n",
       "- **Virtual Methods**:\n",
       "  - `addMiles`: Adds miles to the vehicle.\n",
       "  - `performMaintenance`: Sets the last maintenance mile to the current miles and prints a message.\n",
       "  - `checkMaintenanceDue`: Checks if the vehicle needs maintenance based on the miles traveled since the last maintenance.\n",
       "  - `displayDetails`: Pure virtual function to be implemented by derived classes.\n",
       "  - Destructor: Prints a message indicating the destructor is called.\n",
       "\n",
       "#### Truck and Car Classes\n",
       "\n",
       "- Both derived classes override the `displayDetails` method to provide specific details about the vehicle.\n",
       "\n",
       "### Main Function\n",
       "\n",
       "- A vector of `Vehicle*` is created to store pointers to different types of vehicles.\n",
       "- A `Truck` and a `Car` are created and added to the fleet.\n",
       "- The code iterates over the fleet, calling various methods on each vehicle.\n",
       "- After usage, the dynamically allocated vehicles are deleted to prevent memory leaks.\n",
       "\n",
       "### Red Flags and Best Practices\n",
       "\n",
       "1. **Memory Management**:\n",
       "   - **Red Flag**: The code manually deletes the dynamically allocated `Vehicle` objects. This is error-prone and can lead to memory leaks if not done correctly.\n",
       "   - **Best Practice**: Use smart pointers (`std::unique_ptr` or `std::shared_ptr`) to handle memory automatically.\n",
       "\n",
       "2. **Virtual Destructor**:\n",
       "   - **Red Flag**: The destructor in the `Vehicle` class is not marked as virtual.\n",
       "   - **Best Practice**: Mark the destructor as virtual to ensure proper cleanup of derived class instances when deleted through a base class pointer.\n",
       "\n",
       "3. **Pure Virtual Function**:\n",
       "   - **Best Practice**: The `displayDetails` function is correctly marked as pure virtual in the base class, ensuring derived classes implement it.\n",
       "\n",
       "4. **Code Duplication**:\n",
       "   - **Red Flag**: The `checkMaintenanceDue` and `performMaintenance` methods print messages directly. This can be improved by encapsulating the output logic.\n",
       "   - **Best Practice**: Consider using a separate logging mechanism or at least encapsulate the output in a way that it can be easily modified.\n",
       "\n",
       "5. **Magic Numbers**:\n",
       "   - **Red Flag**: The number 10000 in the `checkMaintenanceDue` method is a magic number.\n",
       "   - **Best Practice**: Define a constant for such values to improve readability and maintainability.\n",
       "\n",
       "### Improved Code\n",
       "\n",
       "Here's an improved version of the code incorporating the best practices mentioned:\n",
       "\n",
       "```cpp\n",
       "#include <iostream>\n",
       "#include <string>\n",
       "#include <vector>\n",
       "#include <memory>\n",
       "\n",
       "class Vehicle {\n",
       "protected:\n",
       "    std::string registrationNumber;\n",
       "    int milesTraveled;\n",
       "    int lastMaintenanceMile;\n",
       "\n",
       "public:\n",
       "    Vehicle(std::string regNum) : registrationNumber(regNum), milesTraveled(0), lastMaintenanceMile(0) {}\n",
       "\n",
       "    virtual void addMiles(int miles) {\n",
       "        milesTraveled += miles;\n",
       "    }\n",
       "\n",
       "    virtual void performMaintenance() {\n",
       "        lastMaintenanceMile = milesTraveled;\n",
       "    }\n",
       "\n",
       "    virtual void checkMaintenanceDue() const {\n",
       "        if ((milesTraveled - lastMaintenanceMile) > MAINTENANCE_INTERVAL) {\n",
       "            std::cout << \"Vehicle: \" << registrationNumber << \" needs maintenance!\" << std::endl;\n",
       "        } else {\n",
       "            std::cout << \"No maintenance required for vehicle: \" << registrationNumber << std::endl;\n",
       "        }\n",
       "    }\n",
       "\n",
       "    virtual void displayDetails() const = 0;\n",
       "\n",
       "    virtual ~Vehicle() {\n",
       "        std::cout << \"Destructor for Vehicle\" << std::endl;\n",
       "    }\n",
       "};\n",
       "\n",
       "class Truck : public Vehicle {\n",
       "    int capacityInTons;\n",
       "\n",
       "public:\n",
       "    Truck(std::string regNum, int capacity) : Vehicle(regNum), capacityInTons(capacity) {}\n",
       "\n",
       "    void displayDetails() const override {\n",
       "        std::cout << \"Truck with Registration Number: \" << registrationNumber << \", Capacity: \" << capacityInTons << \" tons.\" << std::endl;\n",
       "    }\n",
       "};\n",
       "\n",
       "class Car : public Vehicle {\n",
       "    std::string model;\n",
       "\n",
       "public:\n",
       "    Car(std::string regNum, std::string carModel) : Vehicle(regNum), model(carModel) {}\n",
       "\n",
       "    void displayDetails() const override {\n",
       "        std::cout << \"Car with Registration Number: \" << registrationNumber << \", Model: \" << model << \".\" << std::endl;\n",
       "    }\n",
       "};\n",
       "\n",
       "const int MAINTENANCE_INTERVAL = 10000;\n",
       "\n",
       "int main() {\n",
       "    std::vector<std::unique_ptr<Vehicle>> fleet;\n",
       "\n",
       "    fleet.push_back(std::make_unique<Truck>(\"XYZ1234\", 20));\n",
       "    fleet.push_back(std::make_unique<Car>(\"ABC9876\", \"Sedan\"));\n",
       "\n",
       "    for (auto& vehicle : fleet) {\n",
       "        vehicle->displayDetails();\n",
       "        vehicle->addMiles(10500);\n",
       "        vehicle->checkMaintenanceDue();\n",
       "        vehicle->performMaintenance();\n",
       "        vehicle->checkMaintenanceDue();\n",
       "    }\n",
       "\n",
       "    return 0;\n",
       "}\n",
       "```\n",
       "\n",
       "### Summary\n",
       "\n",
       "- **Smart Pointers**: Use `std::unique_ptr` for automatic memory management.\n",
       "- **Virtual Destructor**: Ensure the destructor in the base class is virtual.\n",
       "- **Magic Numbers**: Define constants for magic numbers.\n",
       "- **Encapsulation**: Consider encapsulating output logic to improve flexibility."
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "response = textgen_llm.invoke(prompt)\n",
    "\n",
    "code_explanation = response.content\n",
    "\n",
    "display_markdown(Markdown(code_explanation))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e9abc40",
   "metadata": {},
   "source": [
    "## Summary\n",
    "\n",
    "To conclude we learnt that invoking the LLM without any context might not yield the desired results. By adding context and further using the prompt template to constrain the output from the LLM we are able to successfully get our desired output"
   ]
  }
 ],
 "metadata": {
  "availableInstances": [
   {
    "_defaultOrder": 0,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.t3.medium",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 1,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.t3.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 2,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.t3.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 3,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.t3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 4,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 5,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 6,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 7,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 8,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 9,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 10,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 11,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 12,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5d.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 13,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5d.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 14,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5d.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 15,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5d.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 16,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5d.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 17,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5d.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 18,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5d.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 19,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 20,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": true,
    "memoryGiB": 0,
    "name": "ml.geospatial.interactive",
    "supportedImageNames": [
     "sagemaker-geospatial-v1-0"
    ],
    "vcpuNum": 0
   },
   {
    "_defaultOrder": 21,
    "_isFastLaunch": true,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.c5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 22,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.c5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 23,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.c5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 24,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.c5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 25,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 72,
    "name": "ml.c5.9xlarge",
    "vcpuNum": 36
   },
   {
    "_defaultOrder": 26,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 96,
    "name": "ml.c5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 27,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 144,
    "name": "ml.c5.18xlarge",
    "vcpuNum": 72
   },
   {
    "_defaultOrder": 28,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.c5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 29,
    "_isFastLaunch": true,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g4dn.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 30,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g4dn.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 31,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g4dn.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 32,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g4dn.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 33,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g4dn.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 34,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g4dn.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 35,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 61,
    "name": "ml.p3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 36,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 244,
    "name": "ml.p3.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 37,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 488,
    "name": "ml.p3.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 38,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.p3dn.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 39,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.r5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 40,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.r5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 41,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.r5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 42,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.r5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 43,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.r5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 44,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.r5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 45,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.r5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 46,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.r5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 47,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 48,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 49,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 50,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 51,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 52,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 53,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.g5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 54,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.g5.48xlarge",
    "vcpuNum": 192
   },
   {
    "_defaultOrder": 55,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 56,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4de.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 57,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.trn1.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 58,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.trn1.32xlarge",
    "vcpuNum": 128
   },
   {
    "_defaultOrder": 59,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.trn1n.32xlarge",
    "vcpuNum": 128
   }
  ],
  "instance_type": "ml.t3.medium",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  },
  "vscode": {
   "interpreter": {
    "hash": "00878cbed564b904a98b4a19808853cb6b9988746b881ea025a8408713879bf5"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
